/*
 * @Author: hongbin
 * @Date: 2022-09-22 08:35:12
 * @LastEditors: hongbin
 * @LastEditTime: 2022-10-22 13:25:48
 * @Description:3D制作 关于页
 */
import { initWebGLRenderer } from "./helper/webGLRenderer";
import { intLight } from "./helper/light";
import { windowResize } from "./helper/windowResize";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { stats } from "./helper/stats";
import { initGUI } from "./helper/gui";
import { GUI } from "dat.gui";
import { initGlobalVariable } from "../GlobalVariable";
import { ConstructiveSolidGeometry } from "./helper/CSG";
import fragmentShader from "./shader/glow/glow.fs.glsl";
import vertexShader from "./shader/glow/glow.vt.glsl";

const gui = new GUI();

initGlobalVariable();

export const init = (parameters?: Parameters<typeof initWebGLRenderer>[number]) => {
    const scene = initScene();
    const renderer = initWebGLRenderer(parameters);
    //视野大小 分辨率 最近 最远
    const camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        500
    );
    camera.position.set(0, 2, 4);
    const controls = new OrbitControls(camera, renderer.domElement);

    window.render = function render(e?: number) {
        e && console.log(e);
        renderer.render(scene, camera);
    };
    initGUI();

    windowResize(camera, window.render);

    const tickFunc: (() => void)[] = [];
    const lights = intLight();
    scene.add(...lights);

    const boxGroup = new THREE.Group();
    scene.add(boxGroup);

    const box = new THREE.Mesh(
        new THREE.BoxGeometry(1, 1, 1),
        new THREE.MeshLambertMaterial({ color: 0xff11ff })
    );

    const WrapBox = box.clone();
    WrapBox.scale.x += 0.1;
    WrapBox.scale.y += 0.1;
    WrapBox.scale.z += 0.1;
    // WrapBox.position.set(-0.5, -0.5, -0.5);

    boxGroup.add(box);

    const uniforms = {
        baseColorR: { value: 1 },
        baseColorG: { value: 0 },
        baseColorB: { value: 0 },
        time: { value: 1.5 },
        GeometryWidth: { value: 0.3 },
        GeometryHeight: { value: 0.4 },
        GeometryDepth: { value: 0.2 },
        v1: { value: 1 },
        v2: { value: 0 },
        v3: { value: 0 },
        v4: { value: 1 },
    };

    {
        gui.add(uniforms.v1, "value", -1, 1)
            .name("v1")
            .onChange((v) => console.log(v));
        gui.add(uniforms.v2, "value", -1, 1)
            .name("v2")
            .onChange((v) => console.log(v));
        gui.add(uniforms.v3, "value", -1, 1)
            .name("v3")
            .onChange((v) => console.log(v));
        gui.add(uniforms.v4, "value", -1, 1)
            .name("v4")
            .onChange((v) => console.log(v));
    }

    const resultMeshMaterial = new THREE.ShaderMaterial({
        transparent: true,
        vertexShader,
        fragmentShader,
        uniforms,
        side: 2,
    });

    function generateSprite() {
        const canvas = document.createElement("canvas");
        canvas.width = 16;
        canvas.height = 16;

        const context = canvas.getContext("2d") as any;
        const gradient = context.createRadialGradient(
            canvas.width / 2,
            canvas.height / 2,
            0,
            canvas.width / 2,
            canvas.height / 2,
            canvas.width / 2
        );
        gradient.addColorStop(0, "rgba(255,255,255,1)");
        gradient.addColorStop(0.2, "rgba(0,255,255,1)");
        gradient.addColorStop(0.4, "rgba(0,0,64,1)");
        gradient.addColorStop(1, "rgba(0,0,0,1)");

        context.fillStyle = gradient;
        context.fillRect(0, 0, canvas.width, canvas.height);

        const texture = new THREE.Texture(canvas);
        texture.needsUpdate = true;
        return texture;
    }
    // 创建立方体
    const boxGeometry = new THREE.BoxGeometry(10, 10, 10);
    // 创建粒子材质
    const material = new THREE.PointsMaterial({
        color: 0xffffff,
        size: 3,
        transparent: true,
        blending: THREE.AdditiveBlending,
        map: generateSprite(),
        depthWrite: false,
    });
    // 创建粒子
    const cloud = new THREE.Points(boxGeometry, material);
    scene.add(cloud);

    // const resultMesh = new THREE.Mesh(
    //     new THREE.PlaneGeometry(1, 1, 20, 20),
    //     resultMeshMaterial
    // );
    // resultMesh.position.set(0, 0, 1);
    // const resultMesh = new THREE.Mesh(
    //     ConstructiveSolidGeometry(WrapBox, box, "subtract"),
    //     resultMeshMaterial
    // );
    // resultMesh.position.set(1, 0, 2);
    // scene.add(resultMesh);

    // controls.addEventListener("change", () => {
    //     window.render();
    // });

    // window.render();

    tick.init(() => {
        controls.update();
        window.render();
        // tickFunc.forEach((item) => item());
    });
    tick.run();
    tick.interval = 10;
};

init.stopRender = () => {
    console.log("清除监听");
    tick.clear();
    window.dispatchEvent(new CustomEvent("stoprender"));
};

const tick = {
    animationFrameId: 0,
    script: () => {},
    /**
     * 间隔多少毫秒执行一次
     */
    interval: 200,
    prevTime: 0,
    init: (callback: () => void) => {
        tick.script = callback;
    },
    run: () => {
        tick.animationFrameId = requestAnimationFrame(tick.run);
        stats.update();
        if (performance.now() - tick.prevTime > tick.interval) {
            tick.script();
            tick.prevTime = performance.now();
        }
    },
    clear: () => {
        cancelAnimationFrame(tick.animationFrameId);
    },
};

const initScene = () => {
    const scene = new THREE.Scene();
    // scene.background = new THREE.Color("#51f");
    scene.add(new THREE.AxesHelper(100));
    stats.init();

    return scene;
};
